package com.powernode.service.impl;

//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
//import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.druid.sql.visitor.functions.If;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.powernode.domain.MemberAddr;
import com.powernode.mapper.MemberAddrMapper;
import com.powernode.service.MemberAddrService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionTimedOutException;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Service
@CacheConfig(cacheNames = "com.powernode.service.impl.MemberAddrServiceImpl")
public class MemberAddrServiceImpl extends ServiceImpl<MemberAddrMapper, MemberAddr> implements MemberAddrService {

    @Autowired
    private MemberAddrMapper memberAddrMapper;

    /**
     * 根据OpenId查询会员地址列表
     * <p>
     * 此方法使用缓存机制，以提高查询效率和减少数据库访问压力
     * 缓存键为方法参数openId，确保相同openId的查询结果可以被缓存并复用
     *
     * @param openId 会员的OpenId，用于查询地址信息
     * @return 会员地址列表，按常用地址和创建时间降序排序
     */
    @Override
    @Cacheable(key = "#openId")
    public List<MemberAddr> queryMemberAddrListByOpenId(String openId) {
        // 查询与给定openId关联且状态为1（有效）的会员地址列表，并按常用地址和创建时间降序排序
        List<MemberAddr> list = lambdaQuery().eq(MemberAddr::getOpenId, openId).eq(MemberAddr::getStatus, 1).orderByDesc(MemberAddr::getCommonAddr, MemberAddr::getCreateTime).list();
        return list;
    }

    /**
     * 保存会员地址信息
     *
     * @param memberAddr 会员地址信息
     * @param openId     会员的OpenId
     * @return 如果插入成功返回true，否则返回false
     * @Transactional(rollbackFor = Exception.class) 声明该方法为事务方法，当发生异常时回滚事务
     * @CacheEvict(key = "#openId") 从缓存中移除与openId相关的缓存数据
     */
    // 重写saveMemberAddr方法，用于保存会员地址信息
    @Override
    // 使用事务管理，当方法抛出Exception异常时回滚事务
    @Transactional(rollbackFor = Exception.class)
    // 清除缓存，key为openId，表示当方法执行后，以openId为键的缓存将被清除
    @CacheEvict(key = "#openId")
    public Boolean saveMemberAddr(MemberAddr memberAddr, String openId) {
        // 设置会员地址为非默认地址
        memberAddr.setCommonAddr(0);
        // 设置会员地址状态为有效
        memberAddr.setStatus(1);
        // 设置会员地址的创建时间
        memberAddr.setCreateTime(new Date());
        // 设置会员地址的更新时间
        memberAddr.setUpdateTime(new Date());
        // 设置会员地址关联的openId
        memberAddr.setOpenId(openId);

        // 查询当前openId关联的会员地址数量
        Long count = memberAddrMapper.selectCount(new LambdaQueryWrapper<MemberAddr>().eq(MemberAddr::getOpenId, openId));
        // 如果数量为0，表示这是第一个地址，设置为默认地址
        if (0 == count) {
            memberAddr.setCommonAddr(1);
        }
        // 插入会员地址信息到数据库，如果插入成功返回true，否则返回false
        return memberAddrMapper.insert(memberAddr) > 0;
    }

    /**
     * 修改会员地址信息
     *
     * @param memberAddr 会员地址信息对象
     * @param openId     会员的OpenId
     * @return 如果更新成功返回true，否则返回false
     * @CacheEvict(key = "#openId") 清除缓存，key为openId，表示当方法执行后，以openId为键的缓存将被清除
     */
    @Override
    // 清除缓存，key为openId，表示当方法执行后，以openId为键的缓存将被清除
    @CacheEvict(key = "#openId")
    public Boolean modifyMemberAddrInfo(MemberAddr memberAddr, String openId) {
        memberAddr.setUpdateTime(new Date());
        return memberAddrMapper.updateById(memberAddr) > 0;
    }

    /**
     * 根据地址ID和OpenID删除会员地址信息，如果删除的地址是默认地址，则重新设置默认地址
     *
     * @param addrId 地址ID
     * @param openId OpenID
     * @return 如果删除成功返回true，否则返回false
     */
    // 重写removeMemberAddrById方法，用于删除会员地址信息
    @Override
    // 使用缓存清除注解，当方法执行时，以openId作为key清除缓存
    @CacheEvict(key = "#openId")
    public Boolean removeMemberAddrById(Long addrId, String openId) {
        // 根据地址ID查询会员地址信息
        MemberAddr memberAddr = memberAddrMapper.selectById(addrId);
        // 如果该地址是默认地址（commonAddr字段值为1）
        if (memberAddr.getCommonAddr().equals(1)) {
            // 查询该会员的所有非默认地址，并按创建时间降序排列
            List<MemberAddr> memberAddrs = memberAddrMapper.selectList(new LambdaQueryWrapper<MemberAddr>().eq(MemberAddr::getOpenId, openId).eq(MemberAddr::getCommonAddr, 0).orderByDesc(MemberAddr::getCreateTime));
            // 如果存在非默认地址
            if (CollectionUtil.isNotEmpty(memberAddrs) && memberAddrs.size() != 0) {
                // 获取最新的非默认地址作为新的默认地址
                MemberAddr newDefaultMemberAddr = memberAddrs.get(0);
                // 将新的默认地址标记为默认（commonAddr字段值设为1）
                newDefaultMemberAddr.setCommonAddr(1);
                // 更新新的默认地址的更新时间
                newDefaultMemberAddr.setUpdateTime(new Date());
                // 更新数据库中的默认地址信息
                memberAddrMapper.updateById(newDefaultMemberAddr);
            }
        }
        // 删除指定ID的会员地址信息，并返回是否删除成功（影响行数大于0表示成功）
        return memberAddrMapper.deleteById(addrId) > 0;
    }

    /**
     * 修改会员默认地址
     *
     * @param openId    用户OpenID
     * @param newAddrId 新的默认地址ID
     * @return 如果修改成功返回true，否则返回false
     * @throws IllegalArgumentException 如果提供的newAddrId对应的地址已经是默认地址，则抛出此异常
     */
// 重写修改会员默认地址的方法
    @Override
    // 使用缓存清除注解，当方法执行时，以openId为键清除缓存
    @CacheEvict(key = "#openId")
    @Transactional(rollbackFor = Exception.class)
    public Boolean modifyMemberDefaultAddr(String openId, Long newAddrId) {
        // 根据新的地址ID查询会员地址信息
        MemberAddr newDefaultMemberAddr = memberAddrMapper.selectById(newAddrId);
        // 如果新的地址已经是默认地址，则直接返回true
        if (newDefaultMemberAddr.getCommonAddr().equals(1)) {
            return true;
        }
        // 创建一个会员地址对象用于存储旧的默认地址信息
        MemberAddr oldDefaultMemberAddr = new MemberAddr();
        // 将旧的默认地址的commonAddr字段设置为0，表示取消默认地址
        oldDefaultMemberAddr.setCommonAddr(0);
        // 更新旧默认地址的更新时间
        oldDefaultMemberAddr.setUpdateTime(new Date());
        // 更新旧的默认地址信息，条件是openId相同
        memberAddrMapper.update(oldDefaultMemberAddr, new LambdaQueryWrapper<MemberAddr>().eq(MemberAddr::getOpenId, openId));
        // 将新的地址设置为默认地址，commonAddr字段设置为1
        newDefaultMemberAddr.setCommonAddr(1);
        // 更新新默认地址的更新时间
        newDefaultMemberAddr.setUpdateTime(new Date());
        // 更新新的默认地址信息到数据库，如果更新影响的行数大于0，则返回true，表示操作成功
        return memberAddrMapper.updateById(newDefaultMemberAddr) > 0;
    }


}
